diff options
author | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2011-01-06 11:22:23 +0100 |
---|---|---|
committer | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2011-01-06 11:27:10 +0100 |
commit | 27a2b8fd87f1a34711fab3adcdf1e16f61c4b0b7 (patch) | |
tree | 2e1827dcd7a1e2b15446fa5f41344bf944a94bf2 | |
parent | a6ac1e6c4b9804df54e8e9f6b16d98ae7077e8e7 (diff) |
Fix PathView issues.
-rw-r--r-- | src/graphicsitems/qxpathview.cpp | 197 | ||||
-rw-r--r-- | src/graphicsitems/qxpathview_p.h | 3 | ||||
-rw-r--r-- | src/graphicsitems/qxpathview_p_p.h | 8 |
3 files changed, 137 insertions, 71 deletions
diff --git a/src/graphicsitems/qxpathview.cpp b/src/graphicsitems/qxpathview.cpp index 52060cb..b542d83 100644 --- a/src/graphicsitems/qxpathview.cpp +++ b/src/graphicsitems/qxpathview.cpp @@ -926,97 +926,138 @@ QPointF QxPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) c void QxPathView::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QxPathView); - if (!d->interactive || !d->items.count()) + if (d->interactive) { + d->handleMousePressEvent(event); + event->accept(); + } else { + QxItem::mousePressEvent(event); + } +} + +void QxPathViewPrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_Q(QxPathView); + if (!interactive || !items.count()) return; - QPointF scenePoint = mapToScene(event->pos()); + QPointF scenePoint = q->mapToScene(event->pos()); int idx = 0; - for (; idx < d->items.count(); ++idx) { - QRectF rect = d->items.at(idx)->boundingRect(); - rect = d->items.at(idx)->mapToScene(rect); + for (; idx < items.count(); ++idx) { + QRectF rect = items.at(idx)->boundingRect(); + rect = items.at(idx)->mapToScene(rect); if (rect.contains(scenePoint)) break; } - if (idx == d->items.count() && d->dragMargin == 0.) // didn't click on an item + if (idx == items.count() && dragMargin == 0.) // didn't click on an item return; - d->startPoint = d->pointNear(event->pos(), &d->startPc); - if (idx == d->items.count()) { - qreal distance = qAbs(event->pos().x() - d->startPoint.x()) + qAbs(event->pos().y() - d->startPoint.y()); - if (distance > d->dragMargin) + startPoint = pointNear(event->pos(), &startPc); + if (idx == items.count()) { + qreal distance = qAbs(event->pos().x() - startPoint.x()) + qAbs(event->pos().y() - startPoint.y()); + if (distance > dragMargin) return; } - d->stealMouse = false; - d->lastElapsed = 0; - d->lastDist = 0; - QxItemPrivate::start(d->lastPosTime); - d->tl.clear(); + if (tl.isActive() && flicking) + stealMouse = true; // If we've been flicked then steal the click. + else + stealMouse = false; + + lastElapsed = 0; + lastDist = 0; + QxItemPrivate::start(lastPosTime); + tl.clear(); } + void QxPathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QxPathView); - if (!d->interactive || !d->lastPosTime.isValid()) + if (d->interactive) { + d->handleMouseMoveEvent(event); + if (d->stealMouse) + setKeepMouseGrab(true); + event->accept(); + } else { + QxItem::mouseMoveEvent(event); + } +} + +void QxPathViewPrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + Q_Q(QxPathView); + if (!interactive || !lastPosTime.isValid()) return; qreal newPc; - QPointF pathPoint = d->pointNear(event->pos(), &newPc); - if (!d->stealMouse) { - QPointF delta = pathPoint - d->startPoint; + QPointF pathPoint = pointNear(event->pos(), &newPc); + if (!stealMouse) { + QPointF delta = pathPoint - startPoint; if (qAbs(delta.x()) > QApplication::startDragDistance() || qAbs(delta.y()) > QApplication::startDragDistance()) { - d->stealMouse = true; - d->startPc = newPc; + stealMouse = true; + startPc = newPc; } } - if (d->stealMouse) { - d->moveReason = QxPathViewPrivate::Mouse; - qreal diff = (newPc - d->startPc)*d->model->count()*d->mappedRange; + if (stealMouse) { + moveReason = QxPathViewPrivate::Mouse; + qreal diff = (newPc - startPc)*model->count()*mappedRange; if (diff) { - setOffset(d->offset + diff); + setOffset(offset + diff); - if (diff > d->model->count()/2) - diff -= d->model->count(); - else if (diff < -d->model->count()/2) - diff += d->model->count(); + if (diff > model->count()/2) + diff -= model->count(); + else if (diff < -model->count()/2) + diff += model->count(); - d->lastElapsed = QxItemPrivate::restart(d->lastPosTime); - d->lastDist = diff; - d->startPc = newPc; + lastElapsed = QxItemPrivate::restart(lastPosTime); + lastDist = diff; + startPc = newPc; } - if (!d->moving) { - d->moving = true; - emit movingChanged(); - emit movementStarted(); + if (!moving) { + moving = true; + emit q->movingChanged(); + emit q->movementStarted(); } } } -void QxPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) +void QxPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QxPathView); - d->stealMouse = false; - setKeepMouseGrab(false); - if (!d->interactive || !d->lastPosTime.isValid()) + if (d->interactive) { + d->handleMouseReleaseEvent(event); + event->accept(); + ungrabMouse(); + } else { + QxItem::mouseReleaseEvent(event); + } +} + +void QxPathViewPrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *) +{ + Q_Q(QxPathView); + stealMouse = false; + q->setKeepMouseGrab(false); + if (!interactive || !lastPosTime.isValid()) return; - qreal elapsed = qreal(d->lastElapsed + QxItemPrivate::elapsed(d->lastPosTime)) / 1000.; - qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0; - if (d->model && d->model->count() && qAbs(velocity) > 1.) { - qreal count = d->pathItems == -1 ? d->model->count() : d->pathItems; + qreal elapsed = qreal(lastElapsed + QxItemPrivate::elapsed(lastPosTime)) / 1000.; + qreal velocity = elapsed > 0. ? lastDist / elapsed : 0; + if (model && model->count() && qAbs(velocity) > 1.) { + qreal count = pathItems == -1 ? model->count() : pathItems; if (qAbs(velocity) > count * 2) // limit velocity velocity = (velocity > 0 ? count : -count) * 2; // Calculate the distance to be travelled qreal v2 = velocity*velocity; - qreal accel = d->deceleration/10; + qreal accel = deceleration/10; // + 0.25 to encourage moving at least one item in the flick direction - qreal dist = qMin(qreal(d->model->count()-1), qreal(v2 / (accel * 2.0) + 0.25)); - if (d->haveHighlightRange && d->highlightRangeMode == QxPathView::StrictlyEnforceRange) { + qreal dist = qMin(qreal(model->count()-1), qreal(v2 / (accel * 2.0) + 0.25)); + if (haveHighlightRange && highlightRangeMode == QxPathView::StrictlyEnforceRange) { // round to nearest item. if (velocity > 0.) - dist = qRound(dist + d->offset) - d->offset; + dist = qRound(dist + offset) - offset; else - dist = qRound(dist - d->offset) + d->offset; + dist = qRound(dist - offset) + offset; // Calculate accel required to stop on item boundary if (dist <= 0.) { dist = 0.; @@ -1025,15 +1066,36 @@ void QxPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) accel = v2 / (2.0f * qAbs(dist)); } } - d->moveOffset.setValue(d->offset); - d->tl.accel(d->moveOffset, velocity, accel, dist); - d->tl.callback(QDeclarativeTimeLineCallback(&d->moveOffset, d->fixOffsetCallback, d)); + moveOffset.setValue(offset); + tl.accel(moveOffset, velocity, accel, dist); + tl.callback(QDeclarativeTimeLineCallback(&moveOffset, fixOffsetCallback, this)); + if (!flicking) { + flicking = true; + emit q->flickingChanged(); + emit q->flickStarted(); + } } else { - d->fixOffset(); + fixOffset(); } - d->lastPosTime.invalidate(); - ungrabMouse(); + lastPosTime.invalidate(); + if (!tl.isActive()) + movementEnding(); +} + +void QxPathViewPrivate::movementEnding() +{ + Q_Q(QxPathView); + if (flicking) { + flicking = false; + emit q->flickingChanged(); + emit q->flickEnded(); + } + if (moving && !stealMouse) { + moving = false; + emit q->movingChanged(); + emit q->movementEnded(); + } } bool QxPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) @@ -1041,8 +1103,9 @@ bool QxPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) Q_D(QxPathView); QGraphicsSceneMouseEvent mouseEvent(event->type()); QRectF myRect = mapToScene(QRectF(0, 0, width(), height())); - QxItem *grabber = d->view ? qobject_cast<QxItem*>(d->view->mouseGrabberItem()) : 0; - if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) { + QxItem *grabber = mouseGrabberItem(); + bool stealThisEvent = d->stealMouse; + if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) { mouseEvent.setAccepted(false); for (int i = 0x1; i <= 0x10; i <<= 1) { if (event->buttons() & i) { @@ -1061,6 +1124,7 @@ bool QxPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) break; case QEvent::GraphicsSceneMousePress: mousePressEvent(&mouseEvent); + stealThisEvent = d->stealMouse; break; case QEvent::GraphicsSceneMouseRelease: mouseReleaseEvent(&mouseEvent); @@ -1068,14 +1132,16 @@ bool QxPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) default: break; } - grabber = d->view ? qobject_cast<QxItem*>(d->view->mouseGrabberItem()) : 0; - if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this) + grabber = mouseGrabberItem(); + if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) grabMouse(); return d->stealMouse; } else if (d->lastPosTime.isValid()) { d->lastPosTime.invalidate(); } + if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) + d->stealMouse = false; return false; } @@ -1090,12 +1156,7 @@ bool QxPathView::sceneEventFilter(QxItem *i, QEvent *e) case QEvent::GraphicsSceneMousePress: case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMouseRelease: - { - bool ret = sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e)); - if (e->type() == QEvent::GraphicsSceneMouseRelease) - return ret; - break; - } + return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e)); default: break; } @@ -1364,11 +1425,7 @@ void QxPathView::ticked() void QxPathView::onTimeLineCompleted() { Q_D(QxPathView); - if (d->moving && !d->stealMouse) { - d->moving = false; - emit movingChanged(); - emit movementEnded(); - } + d->movementEnding(); } // find the item closest to the snap position diff --git a/src/graphicsitems/qxpathview_p.h b/src/graphicsitems/qxpathview_p.h index 9c8dee0..64bd2ae 100644 --- a/src/graphicsitems/qxpathview_p.h +++ b/src/graphicsitems/qxpathview_p.h @@ -142,6 +142,9 @@ Q_SIGNALS: void movingChanged(); void movementStarted(); void movementEnded(); + void flickingChanged(); + void flickStarted(); + void flickEnded(); void preferredHighlightBeginChanged(); void preferredHighlightEndChanged(); void highlightRangeModeChanged(); diff --git a/src/graphicsitems/qxpathview_p_p.h b/src/graphicsitems/qxpathview_p_p.h index 210cc7c..d2f0698 100644 --- a/src/graphicsitems/qxpathview_p_p.h +++ b/src/graphicsitems/qxpathview_p_p.h @@ -77,7 +77,7 @@ public: , lastElapsed(0), mappedRange(1.0) , stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true) , autoHighlight(true), highlightUp(false), layoutScheduled(false) - , moving(false) + , moving(false), flicking(false) , dragMargin(0), deceleration(100) , moveOffset(this, &QxPathViewPrivate::setOffset) , firstIndex(-1), pathItems(-1), requestedIndex(-1) @@ -116,6 +116,11 @@ public: } } + void movementEnding(); + void handleMousePressEvent(QGraphicsSceneMouseEvent *event); + void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event); + void handleMouseMoveEvent(QGraphicsSceneMouseEvent *event); + QxItem *getItem(int modelIndex); void releaseItem(QxItem *item); QxPathViewAttached *attached(QxItem *item); @@ -157,6 +162,7 @@ public: bool highlightUp : 1; bool layoutScheduled : 1; bool moving; + bool flicking; QElapsedTimer lastPosTime; QPointF lastPos; qreal dragMargin; |